package com.dragon.logical.service.avttendance.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dragon.common.constant.ContextConfig;
import com.dragon.common.model.ResponseData;
import com.dragon.common.model.ResultCode;
import com.dragon.common.model.exception.CustomException;
import com.dragon.common.util.ExportUtil;
import com.dragon.common.util.StringUtils;
import com.dragon.logical.service.auth.ICalendarService;
import com.dragon.logical.service.avttendance.IAttendanceArrangeService;
import com.dragon.logical.service.avttendance.IAttendanceService;
import com.dragon.logical.service.reminder.IDoReminderService;
import com.dragon.repository.entity.*;
import com.dragon.repository.mapper.*;
import org.apache.poi.ss.usermodel.Font;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 考勤表 服务实现类
 * </p>
 *
 * @author sy
 * @since 2023-07-10
 */
@Service
public class AttendanceServiceImpl extends ServiceImpl<AttendanceMapper, Attendance> implements IAttendanceService {

    @Autowired
    AttendanceMapper attendanceMapper;
    @Autowired
    AttendanceArrangeMapper arrangeMapper;
    @Autowired
    IAttendanceArrangeService attendanceArrangeService;
    @Autowired
    AttendanceChildMapper childMapper;
    @Autowired
    AttendanceLeaveMapper leaveMapper;
    @Autowired
    DailyLogsMapper logsMapper;
    @Autowired
    ArrangePersonnelMapper personnelMapper;
    @Autowired
    ArrangePeriodMapper periodMapper;
    @Autowired
    CalendarMapper calendarMapper;
    @Autowired
    ICalendarService calendarService;
    @Autowired
    ICalendarService service;
    @Autowired
    ArrangePointsMapper pointsMapper;
    @Autowired
    IDoReminderService reminderService;
    @Autowired
    AdminMapper adminMapper;


    @Override
    public Map<String, List<Attendance>> clockList(Integer adminId, String time, Integer attendanceType) {
//        QueryWrapper<Attendance> wrapper = new QueryWrapper<>();
//        wrapper.lambda().eq(adminId!= null,Attendance::getAdminId, adminId)
//                .eq(attendanceType != null, Attendance::getAttendanceType, attendanceType)
//                .apply(StrUtil.isNotBlank(time), " date_format(create_time,'%y%mm%') = date_format('" + time + "-01','%y%mm%')");
//
//        List<Attendance> list = attendanceMapper.selectList(wrapper);
//        list.stream().forEach(s -> s.setJudgmentTime(DateUtil.format(s.getCreateTime(), "yyyy-MM")));
//        Map<String, List<Attendance>> collect = list
//                .stream()
//                .collect(Collectors.groupingBy(Attendance::getJudgmentTime));

        return null;
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void adminInClock(Attendance attendance) {
        //当前打卡时间
        Date time = DateUtil.date();
        attendance.setCreateTime(time);
        //查询配置
        AttendanceArrange arrange = attendanceArrangeService.seeDetailsByAdminId(attendance.getAdminId(),null);
        if (arrange == null){
            throw new CustomException(ResultCode.YOU_NOT_HAVE_ARRANGE);
        }
        //判断智能跳过节假日
        Calendared calendared = calendarService.isWorkDay(time.toString());

        if (arrange.getAutomaticLeave() == 0 && calendared.getIsWorkDay() == false) {
            throw new CustomException(ResultCode.ATTENDANCE_IS_NOT_WORK_DAY);
        }
        String weeks = String.valueOf(DateUtil.dayOfWeek(time));
        if (arrange.getAutomaticLeave() == 1 && !arrange.getRecurry().contains(weeks)) {
            throw new CustomException(ResultCode.ATTENDANCE_IS_NOT_WORK_DAY);
        }
        //获取上班、下班日期
        List<ArrangePeriod> arrangePeriodList = arrange.getPeriodList();

        //上班日期
        Date startTime = DateUtil.parse(DateUtil.format(time, "yyyy-MM-dd").concat(" ").concat(DateUtil.formatTime(arrangePeriodList.get(0).getInTime())));
        //下班日期
        Date endTime = DateUtil.parse(DateUtil.format(time, "yyyy-MM-dd").concat(" ").concat(DateUtil.formatTime(arrangePeriodList.get(0).getOutTime())));

        AttendanceChild attendanceChild = new AttendanceChild();

//        String macByIP = null;
//        try {
//            macByIP = getMacByIP(InetAddress.getLocalHost().getHostAddress());
//        } catch (Exception e) {
//            throw new RuntimeException(e);
//        }

        String ip = getIP();
        attendanceChild.setIp(ip);
//        attendanceChild.setMac(macByIP);
        attendanceChild.setAttendanceTime(time);
        attendanceChild.setAddress(attendance.getAddress());

        // 查询当前是否有数据
        QueryWrapper<Attendance> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Attendance::getAdminId, attendance.getAdminId())
                .eq(Attendance::getCreateTime, DateUtil.today());
        Attendance attendance1 = attendanceMapper.selectOne(queryWrapper);
        // 无数据则添加当天数据
        if (attendance1 == null) {
            // 如果当前时间小于签到时间
            if (time.compareTo(startTime) < 0 || time.compareTo(endTime) < 0) {
                attendanceChild.setClockType(1);
                //外勤打卡
                if (attendance.getIsField() == 1 && time.compareTo(startTime) < 0 ) {
                    attendanceChild.setInClockType(4);
                    attendance.setAttendanceType(1);
                } else {
                    attendanceChild.setInClockType(time.compareTo(startTime) < 0 ? 1 : 2);
                    attendance.setAttendanceType(time.compareTo(startTime) < 0 ? 1 : 3);
                }
                attendanceChild.setStatus(time.compareTo(startTime) < 0 ? 1 : 2);
            } else {
                attendanceChild.setClockType(2);
                attendanceChild.setInClockType(1);
                attendanceChild.setStatus(1);
                //如果直接签退则直接标识主表为异常状态
                attendance.setAttendanceType(3);
            }
            attendanceMapper.insert(attendance);
            attendanceChild.setAttendanceId(attendance.getId());
            //插入考勤
            childMapper.insert(attendanceChild);
        } else {
            //查询子表是否有数据
            List<AttendanceChild> attendanceChild1 = childMapper.selectList(
                    new LambdaQueryWrapper<AttendanceChild>()
                            .eq(AttendanceChild::getAttendanceId, attendance1.getId())
            );
            if (attendanceChild1.size() == 0) {
                Integer attendanceStatus = 0;
                if (time.compareTo(startTime) < 0 || time.compareTo(endTime) < 0) {
                    attendanceChild.setClockType(1);
                    attendanceChild.setAttendanceId(attendance1.getId());
                    attendanceChild.setStatus(time.compareTo(startTime) < 0 ? 1 : 2);
                    attendanceChild.setInClockType(time.compareTo(startTime) < 0 ? 1 : 2);
                    attendanceStatus = time.compareTo(startTime) < 0 ? 0 : 3;
                } else {
                    attendanceChild.setClockType(2);
                    attendanceChild.setInClockType(1);
                    attendanceChild.setStatus(1);
                    attendanceChild.setAttendanceId(attendance1.getId());
                    //如果直接签退则直接标识主表为异常状态
                    attendanceStatus = 3;
                }
                attendance1.setAttendanceType(attendanceStatus);
                attendanceMapper.updateById(attendance1);
                childMapper.insert(attendanceChild);
            } else {
                Integer endId = attendanceChild1.stream().filter(e -> 2 == e.getClockType()).map(AttendanceChild::getId).findFirst().orElse(null);
                attendanceChild.setClockType(2);
                //判断外勤标识
                if (attendance.getIsField() == 1 && time.compareTo(endTime) > 0){
                    attendanceChild.setInClockType(4);
                } else {
                    attendanceChild.setInClockType(time.compareTo(endTime) < 0 ? 3 : 1);
                }
                attendanceChild.setStatus(1);
                if (endId == null) {
                    attendanceChild.setAttendanceId(attendance1.getId());
                    if (attendance1.getAttendanceType() != 3 && time.compareTo(endTime) < 0) {
                        attendanceChild.setStatus(2);
                        attendance1.setAttendanceType(3);
                        attendanceMapper.updateById(attendance1);
                    }
                    childMapper.insert(attendanceChild);
                } else {
                    attendanceChild.setAttendanceId(attendance1.getId());
                    attendanceChild.setId(endId);
                    attendanceChild.setInClockType(time.compareTo(endTime) < 0 ? 3 : 1);
                    attendanceChild.setStatus(time.compareTo(endTime) < 0 ? 2 : 1);
                    attendanceChild.setAttendanceTime(time);
                    childMapper.updateById(attendanceChild);
                }
            }
        }
    }

    @Override
        public List<Map<String,Object>> getAttendMap(List<Integer> adminIds, String time) {

        List<Map<String,Object>> allList = new ArrayList<>();
        //判断时间传或者不传
        if (StrUtil.isBlank(time)){
            //获取时间年月
            time = DateUtil.format(DateUtil.date(),"yyyy-MM");
        }
        if (adminIds == null || adminIds.size() == 0){
            List<ArrangePersonnel> personnelList = personnelMapper.selectList(null);
            adminIds = personnelList.stream().map(ArrangePersonnel::getAdminId).collect(Collectors.toList());
        }

        //获取配置
//        Integer adminId = adminIds.get(0);
//        AttendanceArrange arrange = attendanceArrangeService.seeDetailsByAdminId(adminId, null);
//        List<Integer> weekIds = new ArrayList<>();
//        if (arrange != null){
//            //获取配置的上班日期
//            weekIds = Stream.of(arrange.getRecurry().split(",")).map(Integer::valueOf).collect(Collectors.toList());
//        }
        //获取当前月的天数信息
//        List<Calendared> calendareds = calendarMapper.selectMonthList(time);
//        AtomicReference<Integer> count = new AtomicReference<>(0);
//        Calendar instance = Calendar.getInstance();
//        List<Integer> finalWeekIds = weekIds;
//        calendareds.forEach(calendared -> {
//            Calendared workDay = calendarService.isWorkDay(DateUtil.format(calendared.getODate(), "yyyy-MM-dd"));
//            //判断当前日期是否在 需要打卡的日期list中
//            instance.setTime(DateUtil.date(calendared.getODate()));
//            int week = instance.get(Calendar.DAY_OF_WEEK)-1;
//            if (finalWeekIds.contains(week) == true){
//                count.set(count.get()+1);
//            }
//        });
        Map<String, Object> map = new TreeMap<>();
        map.put("isWork", 26);
        map.put("time", time);
        String companyId = ContextConfig.getCurrentTenantId();
        allList = attendanceMapper.selectMap(adminIds, time, companyId);
        allList.add(map);
        return allList;
    }

    @Override
    public Attendance showDetails(Integer adminId, String time) {
        Date times = null;
        if (StrUtil.isNotBlank(time)) {
            times = DateUtil.parse(time);
        } else {
            times = DateUtil.date();
        }
        QueryWrapper<Attendance> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Attendance::getAdminId, adminId)
                .eq(Attendance::getCreateTime, DateUtil.format(times, "yyyy-MM-dd"));
        Attendance attendance = attendanceMapper.selectOne(wrapper);
        if (attendance == null) {
            attendance = new Attendance();
        }
        attendance.setUsername(attendanceMapper.setAdminName(attendance.getId()));
        QueryWrapper<AttendanceChild> childWrapper = new QueryWrapper<>();
        List<AttendanceChild> attendanceChild = childMapper.selectList(childWrapper.lambda().eq(AttendanceChild::getAttendanceId, attendance.getId()));
        AttendanceChild attendanceChild1 = new AttendanceChild();
        AttendanceChild startId = attendanceChild.stream().filter(e -> 1 == e.getClockType()).findFirst().orElse(null);
        AttendanceChild endId = attendanceChild.stream().filter(e -> 2 == e.getClockType()).findFirst().orElse(null);
        // 获取打卡的配置
        AttendanceArrange arrange = attendanceArrangeService.seeDetailsByAdminId(adminId,attendance.getArrangeId() == null ? null : attendance.getArrangeId());
        if(arrange == null){
            return attendance;
        }
        //判断智能跳过节假日
        Calendared calendared = calendarService.isWorkDay(times.toString());
        if (arrange.getAutomaticLeave() == 0 && calendared.getIsWorkDay() == false) {
            //节假日
            attendance.setAttendanceType(1);
            //签到卡
            attendanceChild1.setStatus(1);
            attendanceChild1.setClockType(1);
            attendanceChild1.setInClockType(0);
            //签退卡
            AttendanceChild attendanceChild2 = new AttendanceChild();
            attendanceChild2.setStatus(1);
            attendanceChild2.setClockType(2);
            attendanceChild2.setInClockType(0);
            attendanceChild.add(attendanceChild1);
            attendanceChild.add(attendanceChild2);
            attendance.setAttendanceChildList(attendanceChild);
            return attendance;
        }
        String weeks = String.valueOf(DateUtil.dayOfWeek(times));
        if (arrange.getAutomaticLeave() == 1 && !arrange.getRecurry().contains(weeks)) {
            // 节假日
            attendance.setAttendanceType(1);
            //签到卡
            attendanceChild1.setStatus(1);
            attendanceChild1.setClockType(1);
            attendanceChild1.setInClockType(0);
            //签退卡
            AttendanceChild attendanceChild2 = new AttendanceChild();
            attendanceChild2.setStatus(1);
            attendanceChild2.setClockType(2);
            attendanceChild2.setInClockType(0);
            attendanceChild.add(attendanceChild1);
            attendanceChild.add(attendanceChild2);
            attendance.setAttendanceChildList(attendanceChild);
            return attendance;
        }
        //获取上班、下班日期
        List<ArrangePeriod> arrangePeriodList = arrange.getPeriodList();
        //下班日期
        Date endTime = DateUtil.parse(DateUtil.format(times, "yyyy-MM-dd").concat(" ").concat(DateUtil.formatTime(arrangePeriodList.get(0).getOutTime())));
        if (startId == null && endId == null) {
            //如果当前时间小于签退时间
            attendanceChild1.setClockType(1);
            attendanceChild1.setInClockType(0);
            //当前时间小于
            if (times.compareTo(endTime) < 0) {
                //判断是否正常
                attendanceChild1.setStatus(DateUtil.today().equals(DateUtil.format(times,"yyyy-MM-dd")) ? 1 : 2);
                attendance.setAttendanceType(DateUtil.today().equals(DateUtil.format(times,"yyyy-MM-dd")) ? 1 : 3);
            } else {
                //判断是否正常
                attendanceChild1.setStatus(2);
                attendance.setAttendanceType(3);
            }
            AttendanceChild attendanceChild2 = new AttendanceChild();
            attendanceChild2.setStatus(DateUtil.today().equals(DateUtil.format(times,"yyyy-MM-dd")) ? 1 : 2);
            attendanceChild2.setClockType(2);
            attendanceChild2.setInClockType(0);
            attendanceChild.add(attendanceChild2);
        }

        if (startId == null && endId != null) {
            //主表为异常状态
            attendance.setAttendanceType(3);
            attendanceChild1.setStatus(2);
            attendanceChild1.setInClockType(0);
            attendanceChild1.setClockType(1);
        }

        if (startId != null && endId == null) {
            //未打卡
            attendanceChild1.setInClockType(0);
            attendanceChild1.setClockType(2);
            attendanceChild1.setStatus(DateUtil.today().equals(DateUtil.format(times,"yyyy-MM-dd")) ? 1 : 2);
        }

        attendanceChild.add(attendanceChild1);
        attendance.setAttendanceChildList(attendanceChild);
        return attendance;
    }

    /**
     * 判断距离
     *
     * @param adminId
     * @param actualLongitude 经度
     * @param actualLatitude  维度
     * @return
     */
    @Override
    public ResponseData determine(Integer adminId, Double actualLongitude, Double actualLatitude) {
        //获取配置的经纬度
        Double latitude = null;
        Double longitude = null;
        double s = 0;
        ArrangePersonnel personnel = personnelMapper.selectOne(
                new LambdaQueryWrapper<ArrangePersonnel>().eq(ArrangePersonnel::getAdminId, adminId)
        );
        if (personnel == null){
            throw new CustomException(ResultCode.YOU_NOT_HAVE_ARRANGE);
        }
        List<ArrangePeriod> period = periodMapper.selectList(new QueryWrapper<ArrangePeriod>().lambda()
                .eq(ArrangePeriod::getArrangeId, personnel.getArrangeId()));
        if (period != null || period.size() == 0) {
            for (ArrangePeriod arrangePeriod : period) {
                String pointsId = arrangePeriod.getPointsId();
                if (StrUtil.isNotBlank(pointsId)) {
                    List<Integer> pid = Stream.of(pointsId.split(",")).map(Integer::parseInt).collect(Collectors.toList());
                    Boolean flag = true;
                    for (Integer integer : pid) {
                        ArrangePoints point = pointsMapper.selectOne(new QueryWrapper<ArrangePoints>()
                                .lambda().eq(ArrangePoints::getId, integer));
                        latitude = point.getLatitude();
                        longitude = point.getLongitude();
                        double radLat1 = latitude * Math.PI / 180.0;
                        double radLat2 = actualLatitude * Math.PI / 180.0;
                        double a = radLat1 - radLat2;
                        double b = longitude * Math.PI / 180.0 - actualLongitude * Math.PI / 180.0;
                        s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
                        s = s * 6371000;
                        s = Math.round(s * 10000) / 10000;
                        if (arrangePeriod.getInClockSetting() != 1 && s > 1000) {
                            flag = false;
                            //return ResponseData.success("可以外勤打卡", 1);
                        } else if (arrangePeriod.getInClockSetting() != 1 && s < 1000) {
                            return ResponseData.success(point);
                        }
                        //当前经纬度不在范围中 就不能打卡
                        if (s < 1000) {
                            Calendar instance = Calendar.getInstance();
                            int i = instance.get(Calendar.DAY_OF_WEEK);
                            AttendanceArrange arrange = arrangeMapper.selectById(personnel.getArrangeId());
                            //获取当前用户需要上班的日期 判断是否需要打卡
                            List<Integer> dates = Stream.of(arrange.getRecurry().split(",")).map(Integer::parseInt).collect(Collectors.toList());
                            if (dates.contains(i) == false) {
                                throw new CustomException(ResultCode.NO_CLOCK_OUT_ON_DAYS_OFF);
                            }
                            //System.out.println("需要打卡");
                            return ResponseData.success(point);
                        }
                    }
                    if (!flag){
                        return ResponseData.success("可以外勤打卡", 1);
                    }
                }

            }
        }
        return ResponseData.error(2077, "此用户没有考勤配置或者不在打卡范围内");
    }


    /**
     * 推送消息
     *
     * @param toId          接收人
     * @param type          通知类型
     * @param operationType 通知流程
     * @param correlationId 主表id
     */
    private void sendPushMsg(Integer toId, Integer type, Integer operationType, Integer correlationId) {
        DoReminder doReminder = new DoReminder();
        //接收人
        doReminder.setAdminId(toId);

        //抄送提醒
        doReminder.setType(type);
        doReminder.setCorrlelationId(correlationId);
        doReminder.setCreateTime(DateUtil.date());
        //doReminder.setUrlAddress(sendReminder.pushUrl());
        doReminder.setOperationType(operationType);
        reminderService.addDoReminder(doReminder);
    }

    /**
     * 获取IPv4 地址
     *
     * @return
     */
    public static String getIP() {
        try {
            Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
            while (allNetInterfaces.hasMoreElements()) {
                NetworkInterface netInterface = allNetInterfaces.nextElement();
                Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                while (addresses.hasMoreElements()) {
                    InetAddress ip = addresses.nextElement();
                    if (ip != null
                            && ip instanceof Inet4Address
                            && !ip.isLoopbackAddress() //loopback地址即本机地址，IPv4的loopback范围是127.0.0.0 ~ 127.255.255.255
                            && ip.getHostAddress().indexOf(":") == -1) {
                        //System.out.println("本机的IP = " + ip.getHostAddress());
                        return ip.getHostAddress();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 判断当前日期是星期几
     *
     * @param pTime 修要判断的时间
     * @return dayForWeek 判断结果
     * @Exception 发生异常
     */
    public static int dayForWeek(String pTime) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(format.parse(pTime));
        int dayForWeek = 0;
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            dayForWeek = 7;
        } else {
            dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
        }
        return dayForWeek;
    }


    /**
     * 获取mac地址
     * @param IP
     * @return
     * @throws Exception
     */
    public static String getMacByIP(String IP) throws Exception {

        InetAddress ia = InetAddress.getByName(IP);
        byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i< mac.length; i ++) {
            if(i != 0) {
                sb.append("-");
            }
            String hexString = Integer.toHexString(mac[i] & 0xFF);
            sb.append(hexString.length() == 1 ? "0" + hexString : hexString);
        }
        return sb.toString().toUpperCase();
    }

    @Override
    public Page<Attendance> attList(Integer page, Integer limit, Integer adminId, String time) {
        Page<Attendance> attendancePage = new Page<>(page, limit);
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy-MM");
        }
        Page<Attendance> attendances = attendanceMapper.selectListBy(attendancePage,adminId,time);
        attendances.getRecords().forEach(attendance -> {
            List<AttendanceChild> attendanceChildren = childMapper.selectList(new QueryWrapper<AttendanceChild>()
                    .lambda()
                    .eq(AttendanceChild::getAttendanceId, attendance.getId()));
            String address = attendanceChildren.stream().map(AttendanceChild::getAddress).collect(Collectors.joining(","));
            attendance.setAddress(address);
            attendance.setAttendanceChildList(attendanceChildren);
            QueryWrapper<AttendanceLeave> wrapper = new QueryWrapper<>();
            wrapper.lambda()
                    .eq(AttendanceLeave::getAttendanceId, attendance.getId())
                    .eq(AttendanceLeave::getAdminId, attendance.getAdminId())
                    .eq(AttendanceLeave::getStatus, 1)
                    .orderByDesc(AttendanceLeave::getCreateTime);
            List<AttendanceLeave> attendanceLeaves = leaveMapper.selectLeaveList(wrapper);
            attendance.setAttendanceLeave(attendanceLeaves);
        });
        return attendances;
    }

    @Override
    public Map<String, Object> getList(Integer adminId, String time) {
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy-MM");
        }
        Map<String, Object> collect = new HashMap<>();
        QueryWrapper<Attendance> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(time)) {
            wrapper.lambda().eq(Attendance::getAdminId, adminId)
                    .apply(" left(create_time,7) = left('" + time + "',7)");
        }
        wrapper.lambda().eq(Attendance::getAdminId, adminId);
        List<Attendance> attendances = attendanceMapper.selectList(wrapper);
        //获取入职时间
        Admin admin = adminMapper.selectById(adminId);


        //获取日期列表
        List<String> timeList = attendanceMapper.selectDateList(time.concat("-01"));
        timeList.forEach(dateString -> {
            attendances.forEach(attendance -> {
                List<AttendanceChild> attendanceChildren = childMapper.selectList(new QueryWrapper<AttendanceChild>().lambda()
                        .eq(AttendanceChild::getAttendanceId, attendance.getId()));
                attendance.setAttendanceChildList(attendanceChildren);
                //匹配到数据
                if (DateUtil.parse(dateString).equals(attendance.getCreateTime())) {
                    // 如果当前时间不等于现在时间则且等于未打卡状态
                    if(attendance.getAttendanceType()==0 && !DateUtil.format(DateUtil.date(),"yyyy-MM-dd").equals(DateUtil.format(attendance.getCreateTime(),"yyyy-MM-dd"))){
                        attendance.setAttendanceType(3);
                        collect.put(dateString,attendance);
                    } else {
                        collect.put(dateString,attendance);
                    }
                } else {
                    //未匹配到数据
                    //当前时间大于开始时间
                    if (DateUtil.parse(dateString).compareTo(admin.getCreateTime()) > 0) {
                        if(DateUtil.parse(dateString).compareTo(DateUtil.date()) < 0){
                            Attendance attendance1 = new Attendance();
                            attendance1.setAttendanceType(3);
                            collect.put(dateString,attendance1);
                        } else {
                            collect.put(dateString,null);
                        }
                    } else {
                        collect.put(dateString,null);
                    }

                }
            });
        });
        return collect;
    }



    @Override
    public Attendance selectArrangeChildDetail(Integer adminId, String time){
        Attendance attendance = showDetails(adminId,time);
        //获取打卡配置
        AttendanceArrange arrange = attendanceArrangeService.seeDetailsByAdminId(adminId,attendance.getArrangeId());
        attendance.setPeriodList(arrange.getPeriodList());
        // 获取请假信息
        List<AttendanceLeave> attendanceLeave = leaveMapper.selectList(
                new LambdaQueryWrapper<AttendanceLeave>()
                        .eq(AttendanceLeave::getAttendanceId,attendance.getId())
                        .eq(AttendanceLeave::getStatus,1)
        );
        attendance.setAttendanceLeave(attendanceLeave.size()==0 ? new ArrayList<>() : attendanceLeave);
        return attendance;
    }

    @Override
    public void exportTotal(String time, HttpServletResponse response) throws IOException {
        //获取数据源的 key, 用于获取列数及设置标题
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy-MM");
        }
        //获取统计信息
        List<Map<String, Object>> attendMap = getAttendMap(null, time);

        ExcelWriter writer = ExcelUtil.getWriter();
        Map<String,String> map = new TreeMap<>();
        map.put("admin_name", "用户名称");
        map.put("shiji", "实际打卡");
        map.put("zaotui", "早退");
        map.put("chidao", "迟到");
        map.put("qingjia", "请假");
        map.put("queka", "缺卡");
        writer.setHeaderAlias(map);

        writer.setColumnWidth(-1,30);
        writer.setRowHeight(-1,25);
        Font font = writer.createFont();
        font.setBold(true);
        writer.merge(map.size() - 1, time+"考勤统计");
        //设置只保留别名的字段
        writer.setOnlyAlias(true);
        writer.write(attendMap,true);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=test.xls");

        ServletOutputStream out= null;
        try {
            out = response.getOutputStream();
            writer.flush(out, true);
            // 关闭writer，释放内存
            writer.close();
            //此处记得关闭输出Servlet流
            IoUtil.close(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void exportList(Integer adminId, String time, HttpServletResponse response) throws UnsupportedEncodingException {
        if (StrUtil.isBlank(time)){
            time = DateUtil.format(DateUtil.date(),"yyyy-MM");
        }
        Page<Attendance> attendancePage = attList(1, 50, adminId, time);
        List<List<Object>> rowTotal = new ArrayList<>();
        List<Object> row1 = CollUtil.newArrayList("姓名", "日期", "上班",  "下班", "状态", "请假开始时间", "请假结束时间", "请假类型");
        rowTotal.add(row1);

        attendancePage.getRecords().forEach(attendance -> {
            AttendanceChild inChild = childMapper.selectOne(new QueryWrapper<AttendanceChild>()
                    .lambda().eq(AttendanceChild::getAttendanceId, attendance.getId())
                    .eq(AttendanceChild::getClockType, 1));
            AttendanceChild outChild = childMapper.selectOne(new QueryWrapper<AttendanceChild>()
                    .lambda().eq(AttendanceChild::getAttendanceId, attendance.getId())
                    .eq(AttendanceChild::getClockType, 2));
            if (inChild == null) {
                inChild = new AttendanceChild();
            }
            if (outChild == null){
                outChild = new AttendanceChild();
            }
            String attendanceType = "";
            //打卡总状态 1.正常, 2、请假、3、异常，4：缺卡
            switch (attendance.getAttendanceType()){
                case 1:
                    attendanceType = "正常";
                    break;
                case 2:
                    attendanceType = "请假";
                    break;
                case 3:
                    attendanceType = "异常";
                    break;
                case 4:
                    attendanceType = "缺卡";
                    break;
                default:
                    attendanceType = "未打卡";
            }
            List<Object> row = CollUtil.newArrayList(
                    attendance.getUsername(),
                    DateUtil.format(attendance.getCreateTime(),"yyyy-MM-dd"),
                    inChild.getAttendanceTime()==null?0:inChild.getAttendanceTime(),
                    outChild.getAttendanceTime()==null?0:outChild.getAttendanceTime(),
                    attendanceType,
                    attendance.getAttendanceLeave().size() ==0 ?0:attendance.getAttendanceLeave().get(0).getStartTime(),
                    attendance.getAttendanceLeave().size() ==0 ?0:attendance.getAttendanceLeave().get(0).getEndTime(),
                    attendance.getAttendanceLeave().size() ==0 ?0:attendance.getAttendanceLeave().get(0).getLeaveTypeName());
            rowTotal.add(row);
        });
        String username = adminMapper.selectUsernameById(adminId);
        //表头
        ExcelWriter writer = ExcelUtil.getWriter();
        writer.setColumnWidth(-1,30);
        writer.setRowHeight(-1,25);
        Font font = writer.createFont();
        font.setBold(true);
        writer.merge(row1.size() - 1, username+"【"+time+"】"+"考勤详情");
        writer.write(rowTotal, true);
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition","attachment;filename=test.xls");
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        writer.flush(out, true);
        // 关闭writer，释放内存
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);

    }

}
